package com.github.fancyideas.jwt;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Data
@Component
@ConfigurationProperties(prefix = "jwt")
public class JwtConfigurationProperties {

    private String authLoginUrl;

    private String jwtSecret;

    // JWT token defaults
    private String tokenHeader;
    private String tokenPrefix;
    private String tokenType;
    private String tokenIssuer;
    private String tokenAudience;
    private Long expiration;

    public String getTokenPrefix() {
        return tokenPrefix + " ";
    }

    // 刷新令牌
    public String refreshToken(String oldToken) {
        Jws<Claims> parsedToken = parsedToken(oldToken);
        String username = getUserName(parsedToken);
        List roles = getResponseRole(parsedToken);
        byte[] signingKey = jwtSecret.getBytes();

        String newToken = Jwts.builder()
                .signWith(Keys.hmacShaKeyFor(signingKey), SignatureAlgorithm.HS512)
                .setHeaderParam("typ", tokenType)
                .setIssuer(tokenIssuer)
                .setAudience(tokenAudience)
                .setSubject(username)
                .setExpiration(new Date(System.currentTimeMillis() + expiration))
                .claim("rol", roles)
                .compact();
        return newToken;
    }

    // token转换为jwtBean
    public Jws<Claims> parsedToken(String token) {
        Jws<Claims> parsedToken = Jwts.parser()
                .setSigningKey(jwtSecret.getBytes())
                .parseClaimsJws(token.replace(tokenPrefix, ""));
        return parsedToken;
    }

    // 获取 username
    public String getUserName(Jws<Claims> parsedToken) {
        String username = parsedToken
                .getBody()
                .getSubject();
        return username;
    }

    // 获取角色 rol，用于返回token，jwt中设置的rol
    public List getResponseRole(Jws<Claims> parsedToken) {
        List authorities = ((List<?>) parsedToken.getBody()
                .get("rol"))
                .stream()
                .map(authority -> new SimpleGrantedAuthority((String) authority).getAuthority())
                .collect(Collectors.toList());
        return authorities;
    }

    // 获取角色 rol，用于认证。
    public List getRole(Jws<Claims> parsedToken) {
        List authorities = ((List<?>) parsedToken.getBody()
                .get("rol"))
                .stream()
                .map(authority -> new SimpleGrantedAuthority((String) authority))
                .collect(Collectors.toList());
        return authorities;
    }
}
